package com.daniel.juc.lock;

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * Synchroized和Lock的区别
 * 1、Synchroized内置的Java关键字，Lock是一个Java类
 * 2、Synchroized无法判断获取锁的状态，Lock可以判断是否获取到了锁
 * 3、Synchroized会自动释放锁，Lock必须要手动释放锁，如果不释放锁，会造成死锁
 * 4、Synchroized线程1（获得锁，阻塞）、线程2（等待，傻傻的等），Lock锁就不一定会等待下去
 * 5、Synchroized可重入锁，非公平，不可以中断，Lock可重入锁，可以判断锁，非公平（可以自己设置）
 * 6、Synchroized适合锁少量的代码同步问题，Lock适合锁大量的同步代码
 *
 * @author Daniel
 * @version V1.0
 * @date 2020/5/18 09:43
 */
public class SaleTicketDemo02 {

	public static void main(String[] args) {
		// 并发：多线程操作同一个资源类，把资源丢入线程
		Ticket2 ticket = new Ticket2();

		new Thread(() -> {
			for (int i = 1; i < 40; i++) {
				ticket.sale();
			}
		}, "A").start();

		new Thread(() -> {
			for (int i = 1; i < 40; i++) {
				ticket.sale();
			}
		}, "B").start();

		new Thread(() -> {
			for (int i = 1; i < 40; i++) {
				ticket.sale();
			}
		}, "C").start();
	}

}

/**
 * Lock三部曲
 * 1、new ReentrantLock()
 * 2、lock.lock() 加锁
 * 3、finally => lock.unlock() 解锁
 */
class Ticket2 {
	/**
	 * 总数量
	 */
	private int number = 30;

	Lock lock = new ReentrantLock();

	public synchronized void sale() {
		//加锁
		lock.lock();
		try {
			while (number > 0) {
				System.out.println(Thread.currentThread().getName() + "卖出了" + (number--) + "票，剩余：" + number);
			}
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			// 解锁
			lock.unlock();
		}

	}
}
